#include <qqtdatacache.h>
#include <qqthostaddressmanager.h>

enum MsgSecName
{
    CMD_TYPE = 0,
    CMD_CONTENT,
    CMD_MAX
};

QQtCalculateProtocol::QQtCalculateProtocol ( QObject* parent )
    : QQtDataProtocol ( parent ) {}

QQtCalculateProtocol::~QQtCalculateProtocol() {}

int QQtCalculateProtocol::sendValue ( int value )
{
    QQtDataSerialization data;
    data[CMD_TYPE] = "cal";
    data[CMD_CONTENT] = value;
    data.serialize();
    p3line() << data[CMD_TYPE].getValue().toString() << data[CMD_CONTENT].getValue().toInt();
    sendMessage ( data );
}

void QQtCalculateProtocol::recvMessage ( const QQtDataSerialization& data )
{
    const QQtDataSerialization& ds0 = data;
    QString cmd_type = ds0[CMD_TYPE].getValue().toString();
    if ( cmd_type == "cal_ack" )
    {
        p3line() << cmd_type << ds0[CMD_CONTENT].getValue().toInt();
    }
}

QQtCalculateManager::QQtCalculateManager ( QObject* parent ) : QObject ( parent )
{
    c0 = new QQtUdpClient ( this );
    p0 = new QQtCalculateProtocol ( this );
    c0->installProtocol ( p0 );

    QQtHostAddressManager manager;
    QString ip = manager.getHostAddress();
    int port = 4418;
#if USE_HOST_ADDRESS
    c0->bind ( QHostAddress ( ip ), port, QQtUdpClient::DefaultForPlatform );
#else
    c0->bind ( port, QQtUdpClient::DefaultForPlatform );
#endif
    p3line() << c0->localAddress() << c0->localPort();

    c0->setServerAddress ( QHostAddress ( ip ), 4417 );
}

QQtCalculateManager::~QQtCalculateManager() {}

void QQtCalculateManager::setServerAddress ( QHostAddress address, int port )
{
    c0->setServerAddress ( address, port );
}

void QQtCalculateManager::setListeningAddress ( QHostAddress address, int port )
{
    c0->disconnectFromHost();
    c0->bind ( address, port, QQtUdpClient::DefaultForPlatform );
    p3line() << c0->localAddress() << c0->localPort();
}

void QQtCalculateManager::setListeningPort ( int port )
{
    c0->disconnectFromHost();
    QQtHostAddressManager manager;
    QString ip = manager.getHostAddress();
#if USE_HOST_ADDRESS
    c0->bind ( QHostAddress ( ip ), port, QQtUdpClient::DefaultForPlatform );
#else
    c0->bind ( port, QQtUdpClient::DefaultForPlatform );
#endif
    p3line() << c0->localAddress() << c0->localPort();
}

void QQtCalculateManager::sendValue ( int value )
{
    p0->sendValue ( value );
}

QQtCalculateServerProtocol::QQtCalculateServerProtocol ( QObject* parent )
    : QQtDataProtocol ( parent ) {}

QQtCalculateServerProtocol::~QQtCalculateServerProtocol() {}

int QQtCalculateServerProtocol::recvValue ( int value )
{
    emit signalRecvValue ( value );
    sendCalAck();
}

void QQtCalculateServerProtocol::sendCalAck()
{
    QQtDataSerialization data;
    data[CMD_TYPE] = "cal_ack";
    data[CMD_CONTENT] = 200;
    data.serialize();
    p3line() << data[CMD_TYPE].getValue().toString() << data[CMD_CONTENT].getValue().toInt();
    sendMessage ( data );
}

void QQtCalculateServerProtocol::recvMessage ( const QQtDataSerialization& data )
{
    const QQtDataSerialization& ds0 = data;
    QString cmd_type = ds0[CMD_TYPE].getValue().toString();
    if ( cmd_type == "cal" )
    {
        p3line() << cmd_type << ds0[CMD_CONTENT].getValue().toInt();
        recvValue ( ds0[CMD_CONTENT].getValue().toInt() );
    }
}

QQtCalculateServerProtocolManager::QQtCalculateServerProtocolManager ( QObject* parent )
    : QQtProtocolManager ( parent ) {}

QQtCalculateServerProtocolManager::~QQtCalculateServerProtocolManager() {}

QQtProtocol* QQtCalculateServerProtocolManager::createProtocol()
{
    QQtCalculateServerProtocol* p = ( QQtCalculateServerProtocol* ) QQtProtocolManager::createProtocol();
    connect ( p, SIGNAL ( signalRecvValue ( int ) ),
              this, SIGNAL ( signalRecvValue ( int ) ) );
    return p;
}

QQtCalculateServerManager::QQtCalculateServerManager ( QObject* parent )
    : QObject ( parent )
{
    s0 = new QQtUdpServer ( this );
    m0 = new QQtCalculateServerProtocolManager ( this );
    m0->registerProtocol<QQtCalculateServerProtocol>();
    s0->installProtocolManager ( m0 );

    connect ( m0, SIGNAL ( remainingProtocolChanged ( int ) ),
              this, SLOT ( remainingProtocolChanged ( int ) ) );

    connect ( m0, SIGNAL ( signalRecvValue ( int ) ),
              this, SIGNAL ( signalRecvValue ( int ) ) );

    QQtHostAddressManager manager;
    QString ip = manager.getHostAddress();
    int port = 4417;
#if USE_HOST_ADDRESS
    s0->bind ( QHostAddress ( ip ), port, QQtUdpServer::DefaultForPlatform );
#else
    s0->bind ( port, QQtUdpServer::DefaultForPlatform );
#endif
    p3line() << s0->localAddress() << s0->localPort();
}

QQtCalculateServerManager::~QQtCalculateServerManager() {}

void QQtCalculateServerManager::setListeningAddress ( QHostAddress address, int port )
{
    s0->disconnectFromHost();
    s0->bind ( address, port, QQtUdpServer::DefaultForPlatform );
    p3line() << s0->localAddress() << s0->localPort();
}

void QQtCalculateServerManager::setListeningPort ( int port )
{
    s0->disconnectFromHost();
    QQtHostAddressManager manager;
    QString ip = manager.getHostAddress();
#if USE_HOST_ADDRESS
    s0->bind ( QHostAddress ( ip ), port, QQtUdpServer::DefaultForPlatform );
#else
    s0->bind ( port, QQtUdpServer::DefaultForPlatform );
#endif
    p3line() << s0->localAddress() << s0->localPort();
}

void QQtCalculateServerManager::remainingProtocolChanged ( int num )
{
    if ( num > 10 )
        return;
    m0->registerProtocol<QQtCalculateServerProtocol>();
}
